package com.changgou.seckill.service.impl;

import com.alibaba.fastjson.JSON;
import com.changgou.seckill.dao.SeckillGoodsMapper;
import com.changgou.seckill.dao.SeckillOrderMapper;
import com.changgou.seckill.pojo.SeckillGoods;
import com.changgou.seckill.pojo.SeckillOrder;
import com.changgou.seckill.pojo.SeckillStatus;
import com.changgou.seckill.service.SeckillOrderService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;
import java.util.List;

/****
 * @Author:itheima
 * @Description:SeckillOrder业务层接口实现类
 *****/
@Service
public class SeckillOrderServiceImpl implements SeckillOrderService {

    @Autowired
    private SeckillOrderMapper seckillOrderMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    /**
     * 查询支付状态
     *
     * @param username
     */
    @Override
    public SeckillStatus findPayStatus(String username) {
        String stringSeckillStatus = stringRedisTemplate.boundValueOps("SeckillStatus_" + username).get();
        return JSON.parseObject(stringSeckillStatus, SeckillStatus.class);
    }

    /**
     * 支付失败==>删除订单,回滚库存
     *
     * @param username
     */
    @Override
    public void closeOrder(String username) {
        //获取订单状态信息
        String stringSeckillStatus = stringRedisTemplate.boundValueOps("SeckillStatus_" + username).get();
        //转为对象
        SeckillStatus seckillStatus = JSON.parseObject(stringSeckillStatus, SeckillStatus.class);

        //获取对应的商品信息
        SeckillGoods seckillGoods = (SeckillGoods) redisTemplate.boundHashOps("SeckillGoods_" + seckillStatus.getTime()).get(seckillStatus.getGoodsId());

        if (seckillGoods == null) {
            /**
             * 没获取到商品,说明商品已经售罄,售罄时会同步到数据库
             *      1. 修改数据库,数据库中的库存数量需要 +1
             */
            //查询数据库
            seckillGoods = seckillGoodsMapper.selectByPrimaryKey(seckillGoods.getId());
            //设置剩余库存数 +1
            seckillGoods.setStockCount(seckillGoods.getStockCount() + 1);
            //同步到数据库
            seckillGoodsMapper.updateByPrimaryKeySelective(seckillGoods);
        }
        //删除redis中保存的订单
        redisTemplate.boundHashOps("SeckillOrder").delete(username);
    }

    /**
     * 修改订单状态
     *
     * @param username      用户名
     * @param transactionId 微信支付返回的交易流水号
     */
    @Override
    public void updatePayStatus(String username, String transactionId) {
        //从redis中根据用户名获取订单信息
        SeckillOrder seckillOrder = (SeckillOrder) redisTemplate.boundHashOps("SeckillOrder").get(username);
        //支付时间
        seckillOrder.setPayTime(new Date());
        //微信支付交易流水号
        seckillOrder.setTransactionId(transactionId);
        //已支付
        seckillOrder.setStatus("1");

        //同步到数据库中
        seckillOrderMapper.insertSelective(seckillOrder);

        //删除redis中保存的订单数据
        redisTemplate.boundHashOps("SeckillOrder").delete(username);

        //更新用户状态
        //清除抢单信息
        stringRedisTemplate.delete("SeckillStatus_" + username);
        //清除排队信息
        redisTemplate.delete("UserQueueCount_" + username);
    }

    /**
     * 秒杀抢单=========队列消峰 将抢单信息放入rabbitmq
     * @param username 抢单的用户名
     * @param id       抢单的商品id
     * @param time     抢单的商品属于的时间段
     * @return
     */
    @Override
    public Boolean add(String username, String id, String time) {

        /**
         * 在redis中定义一个变量,用户每次进入这个方法,都让这个变量+1
         * 如果这个变量 > 1 说明==>该用户已经进入排队状态
         * 不允许重复排队,抛异常终止程序 异常状态码 100
         */
        Long increment = redisTemplate.boundValueOps("UserQueueCount_" + username).increment(1);
        if (increment > 1) {
            //表示已经进入排队状态  === 手动异常终止  状态码 100
            System.out.println("重复排队,当前已进入排队状态....");
            throw new RuntimeException("100");
        }

        //封装抢单信息
        SeckillStatus seckillStatus = new SeckillStatus();
        seckillStatus.setUsername(username);
        seckillStatus.setCreateTime(new Date());
        //排队
        seckillStatus.setStatus(1);
        //商品id
        seckillStatus.setGoodsId(id);
        //商品所属时间段
        seckillStatus.setTime(time);
        //转成json格式字符串
        String jsonSeckillStatus = JSON.toJSONString(seckillStatus);
        //发送消息至队列
        rabbitTemplate.convertAndSend("seckillOrderExchange", "seckillOrderQueue",jsonSeckillStatus );

        //抢单信息存入redis
        stringRedisTemplate.boundValueOps("SeckillStatus_"+username).set(jsonSeckillStatus);
        return true;
    }

    /**
     * SeckillOrder条件+分页查询
     * @param seckillOrder 查询条件
     * @param page 页码
     * @param size 页大小
     * @return 分页结果
     */
    @Override
    public PageInfo<SeckillOrder> findPage(SeckillOrder seckillOrder, int page, int size){
        //分页
        PageHelper.startPage(page,size);
        //搜索条件构建
        Example example = createExample(seckillOrder);
        //执行搜索
        return new PageInfo<SeckillOrder>(seckillOrderMapper.selectByExample(example));
    }

    /**
     * SeckillOrder分页查询
     * @param page
     * @param size
     * @return
     */
    @Override
    public PageInfo<SeckillOrder> findPage(int page, int size){
        //静态分页
        PageHelper.startPage(page,size);
        //分页查询
        return new PageInfo<SeckillOrder>(seckillOrderMapper.selectAll());
    }

    /**
     * SeckillOrder条件查询
     * @param seckillOrder
     * @return
     */
    @Override
    public List<SeckillOrder> findList(SeckillOrder seckillOrder){
        //构建查询条件
        Example example = createExample(seckillOrder);
        //根据构建的条件查询数据
        return seckillOrderMapper.selectByExample(example);
    }


    /**
     * SeckillOrder构建查询对象
     * @param seckillOrder
     * @return
     */
    public Example createExample(SeckillOrder seckillOrder){
        Example example=new Example(SeckillOrder.class);
        Example.Criteria criteria = example.createCriteria();
        if(seckillOrder!=null){
            // 主键
            if(!StringUtils.isEmpty(seckillOrder.getId())){
                    criteria.andEqualTo("id",seckillOrder.getId());
            }
            // 秒杀商品ID
            if(!StringUtils.isEmpty(seckillOrder.getSeckillId())){
                    criteria.andEqualTo("seckillId",seckillOrder.getSeckillId());
            }
            // 支付金额
            if(!StringUtils.isEmpty(seckillOrder.getMoney())){
                    criteria.andEqualTo("money",seckillOrder.getMoney());
            }
            // 用户
            if(!StringUtils.isEmpty(seckillOrder.getUserId())){
                    criteria.andEqualTo("userId",seckillOrder.getUserId());
            }
            // 创建时间
            if(!StringUtils.isEmpty(seckillOrder.getCreateTime())){
                    criteria.andEqualTo("createTime",seckillOrder.getCreateTime());
            }
            // 支付时间
            if(!StringUtils.isEmpty(seckillOrder.getPayTime())){
                    criteria.andEqualTo("payTime",seckillOrder.getPayTime());
            }
            // 状态，0未支付，1已支付
            if(!StringUtils.isEmpty(seckillOrder.getStatus())){
                    criteria.andEqualTo("status",seckillOrder.getStatus());
            }
            // 收货人地址
            if(!StringUtils.isEmpty(seckillOrder.getReceiverAddress())){
                    criteria.andEqualTo("receiverAddress",seckillOrder.getReceiverAddress());
            }
            // 收货人电话
            if(!StringUtils.isEmpty(seckillOrder.getReceiverMobile())){
                    criteria.andEqualTo("receiverMobile",seckillOrder.getReceiverMobile());
            }
            // 收货人
            if(!StringUtils.isEmpty(seckillOrder.getReceiver())){
                    criteria.andEqualTo("receiver",seckillOrder.getReceiver());
            }
            // 交易流水
            if(!StringUtils.isEmpty(seckillOrder.getTransactionId())){
                    criteria.andEqualTo("transactionId",seckillOrder.getTransactionId());
            }
        }
        return example;
    }

    /**
     * 删除
     * @param id
     */
    @Override
    public void delete(String id){
        seckillOrderMapper.deleteByPrimaryKey(id);
    }

    /**
     * 修改SeckillOrder
     * @param seckillOrder
     */
    @Override
    public void update(SeckillOrder seckillOrder){
        seckillOrderMapper.updateByPrimaryKey(seckillOrder);
    }

    /**
     * 增加SeckillOrder
     * @param seckillOrder
     */
    @Override
    public void add(SeckillOrder seckillOrder){
        seckillOrderMapper.insert(seckillOrder);
    }

    /**
     * 根据ID查询SeckillOrder
     * @param id
     * @return
     */
    @Override
    public SeckillOrder findById(String id){
        return  seckillOrderMapper.selectByPrimaryKey(id);
    }

    /**
     * 查询SeckillOrder全部数据
     * @return
     */
    @Override
    public List<SeckillOrder> findAll() {
        return seckillOrderMapper.selectAll();
    }
}
